#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <pthread.h>
#include "blockQueue.hpp"
#include "task.hpp"
using namespace std;
using Yohifo::BlockQueue;
using Yohifo::Info;
using Yohifo::Task;

// void *consumer(void *args)
// {
//     BlockQueue<int>* bq = static_cast<BlockQueue<int>*>(args);

//     while(true)
//     {
//         //1、消费者从阻塞队列中获取数据
//         //2、消费者根据数据执行一定的业务

//         int data;
//         bq->pop(data);

//         //TODO
//         cout << pthread_self() << " | " << "消费者拿到了数据: " << data << endl;
//     }
// }

void *consumer(void *args)
{
    // Info<int>* info = static_cast<Info<int>*>(args);
    Info<Task<double>> *info = static_cast<Info<Task<double>> *>(args);

    while (true)
    {
        // 1、消费者从阻塞队列中获取数据
        // 2、消费者根据数据执行一定的业务

        // int data;
        Task<double> data;
        info->_pq->pop(data);

        // TODO
        //  cout << info->_name << " | " << "消费者拿到了数据: " << data << endl;

        data();

        cout << info->_name << " | " << data.getOutcome() << endl;

        sleep(1);
    }
}

// void *producer(void *args)
// {
//     BlockQueue<int>* bq = static_cast<BlockQueue<int>*>(args);

//     while(true)
//     {
//         //1、生产者生产数据
//         //2、放入阻塞队列中

//         int data = rand() % 10 + 1;
//         bq->push(data);
//     }
// }

void *producer(void *args)
{
    // Info<int>* info = static_cast<Info<int>*>(args);
    Info<Task<double>> *info = static_cast<Info<Task<double>> *>(args);

    string opArray = "+-*/%";
    char op = opArray[rand() % opArray.size()];

    while (true)
    {
        // 1、生产者生产数据
        // 2、放入阻塞队列中

        // int data = rand() % 10 + 1;

        int x = rand() % 20 + 1;
        int y = rand() % 20 + 1;

        Task<double> data(x, y, op);
        info->_pq->push(data);

        cout << info->_name << " | " << data.getExpre() << endl;
        sleep(1);
    }
}

int main()
{
    srand((size_t)time(NULL));
    // BlockQueue<int>* bq = new BlockQueue<int>();
    BlockQueue<Task<double>> *bq = new BlockQueue<Task<double>>();

    // //生产者生产，消费者消费
    // pthread_t c, p;

    // pthread_create(&c, nullptr, consumer, bq);
    // pthread_create(&p, nullptr, producer, bq);

    // pthread_join(c, nullptr);
    // pthread_join(p, nullptr);

    int n = 5;
    int m = 5;
    Info<Task<double>> arrC[n];
    Info<Task<double>> arrP[m];

    for (int i = 0; i < n; i++)
    {
        char buff[64];
        snprintf(buff, sizeof(buff), "thread con-%d", i);
        arrC[i]._name = buff;
        arrC[i]._pq = bq;
        pthread_create(&arrC[i]._id, nullptr, consumer, &arrC[i]);
    }

    for (int i = 0; i < m; i++)
    {
        char buff[64];
        snprintf(buff, sizeof(buff), "thread por-%d", i);
        arrP[i]._name = buff;
        arrP[i]._pq = bq;
        pthread_create(&arrP[i]._id, nullptr, producer, &arrP[i]);
    }

    for (int i = 0; i < n; i++)
        pthread_join(arrC[i]._id, nullptr);

    for (int i = 0; i < m; i++)
        pthread_join(arrP[i]._id, nullptr);

    delete bq;

    return 0;
}